#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import psycopg2
import requests
import json
import time
import logging
from urllib.parse import quote, unquote

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/Volumes/jdssd5/Project/python/pytools/music/music_search.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)

class MusicSearcher:
    def __init__(self, db_config):
        self.db_config = db_config
        self.headers = {
            'accept': '*/*',
            'accept-language': 'zh-CN,zh;q=0.9',
            'priority': 'u=1, i',
            'sec-ch-ua': '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"',
            'sec-ch-ua-mobile': '?0',
            'sec-ch-ua-platform': '"macOS"',
            'sec-fetch-dest': 'empty',
            'sec-fetch-mode': 'cors',
            'sec-fetch-site': 'same-site',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'
        }
        
    def connect_db(self):
        """连接数据库"""
        try:
            conn = psycopg2.connect(**self.db_config)
            return conn
        except Exception as e:
            logging.error(f"数据库连接失败: {e}")
            return None
    
    def search_songs(self, keyword):
        """根据关键字搜索歌曲"""
        try:
            # URL编码关键字
            encoded_keyword = quote(keyword)
            url = f"https://api.qqmp3.vip/api/songs.php?type=search&keyword={encoded_keyword}"
            
            logging.info(f"搜索关键字: {keyword}")
            response = requests.get(url, headers=self.headers, timeout=10)
            
            if response.status_code == 200:
                data = response.json()
                if data.get('code') == 200:
                    songs = data.get('data', [])
                    logging.info(f"搜索完成，找到 {len(songs)} 首歌曲")
                    return songs
                else:
                    logging.error(f"搜索失败: {data.get('message', '未知错误')}")
            else:
                logging.error(f"HTTP请求失败，状态码: {response.status_code}")
        except Exception as e:
            logging.error(f"搜索歌曲时出错: {e}")
        return []
    
    def save_songs_to_db(self, songs):
        """将歌曲数据保存到数据库"""
        if not songs:
            logging.warning("没有歌曲数据需要保存")
            return 0
            
        conn = self.connect_db()
        if not conn:
            return 0
            
        saved_count = 0
        try:
            cursor = conn.cursor()
            
            for song_data in songs:
                try:
                    # 插入音乐数据
                    insert_music_sql = """
                    INSERT INTO music (rid, name, artist, pic, src, file_path, extracted_song_name, extracted_artist)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                    ON CONFLICT (rid) DO NOTHING
                    RETURNING id;
                    """
                    
                    cursor.execute(insert_music_sql, (
                        song_data.get('rid'),
                        song_data.get('name'),
                        song_data.get('artist'),
                        song_data.get('pic').replace('\\', '') if song_data.get('pic') else None,
                        song_data.get('src').replace('\\', '') if song_data.get('src') else None,
                        None,  # file_path
                        song_data.get('name'),  # extracted_song_name
                        song_data.get('artist')  # extracted_artist
                    ))
                    
                    result = cursor.fetchone()
                    if result:
                        music_id = result[0]
                        conn.commit()
                        
                        # 插入下载链接数据
                        if 'downurl' in song_data and song_data['downurl']:
                            for downurl_item in song_data['downurl']:
                                if '$$' in downurl_item:
                                    url_type, url_value = downurl_item.split('$$', 1)
                                    formatted_url = f"{url_type}: {url_value}"
                                    
                                    insert_download_url_sql = """
                                    INSERT INTO music_download_url (music_id, url_type, url_value, formatted_url)
                                    VALUES (%s, %s, %s, %s)
                                    ON CONFLICT DO NOTHING;
                                    """
                                    
                                    cursor.execute(insert_download_url_sql, (
                                        music_id,
                                        url_type,
                                        url_value,
                                        formatted_url
                                    ))
                        
                        # 保存原始JSON数据
                        insert_raw_data_sql = """
                        INSERT INTO music_raw_data (rid, raw_json)
                        VALUES (%s, %s)
                        ON CONFLICT (rid) DO NOTHING;
                        """
                        
                        cursor.execute(insert_raw_data_sql, (
                            song_data.get('rid'),
                            json.dumps(song_data, ensure_ascii=False)
                        ))
                        
                        conn.commit()
                        saved_count += 1
                        logging.info(f"成功保存歌曲: {song_data.get('name')} - {song_data.get('artist')}")
                    else:
                        logging.debug(f"歌曲已存在，跳过: {song_data.get('name')} - {song_data.get('artist')}")
                        
                except Exception as e:
                    logging.error(f"保存单首歌曲时出错: {e}")
                    conn.rollback()
                    
            cursor.close()
            conn.close()
            
            logging.info(f"成功保存 {saved_count} 首新歌曲到数据库")
            return saved_count
        except Exception as e:
            logging.error(f"保存歌曲到数据库时出错: {e}")
            if conn:
                conn.rollback()
                conn.close()
            return 0
    
    def search_and_save(self, keyword):
        """搜索关键字并保存结果到数据库"""
        logging.info(f"开始搜索关键字: {keyword}")
        
        # 搜索歌曲
        songs = self.search_songs(keyword)
        
        if not songs:
            logging.warning(f"未找到与 '{keyword}' 相关的歌曲")
            return 0
            
        # 保存到数据库
        saved_count = self.save_songs_to_db(songs)
        logging.info(f"搜索完成，新增 {saved_count} 首歌曲")
        return saved_count

def main():
    import argparse
    
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='搜索音乐并保存到数据库')
    parser.add_argument('keyword', help='搜索关键字')
    parser.add_argument('--host', default='localhost', help='数据库主机')
    parser.add_argument('--database', default='postgres', help='数据库名')
    parser.add_argument('--user', default='lijun', help='数据库用户名')
    parser.add_argument('--password', default='kuaile9hao', help='数据库密码')
    parser.add_argument('--port', type=int, default=5432, help='数据库端口')
    
    args = parser.parse_args()
    
    # 数据库配置
    db_config = {
        'host': args.host,
        'database': args.database,
        'user': args.user,
        'password': args.password,
        'port': args.port
    }
    
    # 创建搜索器实例
    searcher = MusicSearcher(db_config)
    
    # 执行搜索和保存
    try:
        saved_count = searcher.search_and_save(args.keyword)
        print(f"搜索完成，成功保存 {saved_count} 首新歌曲到数据库")
    except Exception as e:
        logging.error(f"搜索过程中出现错误: {e}")
        print(f"搜索失败: {e}")

if __name__ == "__main__":
    main()